package com.czz.zuul.filter;

import com.czz.zuul.utils.ArrayAuthUtils;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;

/**
 * @ClassName: AuthFilter
 * @Author Czz
 * @Date 2020/2/24
 * @Time 16:57
 **/
@Component
public class AuthFilter extends ZuulFilter {

    @Autowired
    private StringRedisTemplate redisTemplate;

    static final String USER_PREFIX = "user:token:";
    static final String TEACHER_PREFIX = "teacher:token:";
    static final String ADMIN_PREFIX = "admin:token:";

    static final String[] USER_WHITE = new String[] {"/portal", "/ucenter/user"};
    static final String[] TEACHER_WHITE = new String[] {"/manage/teacher", "/ucenter/teacher", "/vod/teacher"};
    static final String[] ADMIN_WHITE = new String[] {"/manage/admin", "/ucenter/admin"};


    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        //管理员与讲师全部拦截，门户页面拦截post,put,delete请求
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //获取请求方式
        String method = request.getMethod();
        //获取请求地址
        String url = request.getRequestURI();

        //System.out.println("url："+ url + "\nmethod："+method);

        //跨域预检请求不过滤
        if (method.equals("OPTIONS")) return false;

        //门户页面的GET请求不拦截
        if (url.contains("portal") && method.equals("GET")){
            return false;
        }

        //支付宝支付回调不拦截
        if (url.contains("notify_url") || url.contains("return_url")){
            return false;
        }

        //注册登录及验证码请求不拦截
        if (url.contains("login") || url.contains("register") || url.contains("kaptcha")){
            return false;
        }

        //发送注册验证码请求不拦截
        if (url.contains("/ucenter/user/users/sms") || url.contains("/ucenter/user/users/check")){
            return false;
        }

        //token验证不拦截
        if (url.contains("/verify")){
            return false;
        }

        //阿里云oss不拦截
        if (url.contains("/oss")){
            return false;
        }

        //其余请求全部过滤
        return true;
    }

    @Override
    public Object run() throws ZuulException{
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //获取请求方式
        String method = request.getMethod();
        //获取请求地址
        String url = request.getRequestURI();

        //门户
        if (ArrayAuthUtils.ArrayContains(USER_WHITE,url)){
            //从header中取出USER-TOKEN及USER-ID
            String token = request.getHeader("USER-TOKEN");
            String userId = request.getHeader("USER-ID");
            verifyTokenAndId(token,userId,USER_PREFIX,requestContext);
            return null;
        }

        //讲师
        if (ArrayAuthUtils.ArrayContains(TEACHER_WHITE,url)){
            //从header中取出TEACHER-TOKEN及TEACHER-ID
            String token = request.getHeader("TEACHER-TOKEN");
            String teacherId = request.getHeader("TEACHER-ID");
            verifyTokenAndId(token,teacherId,TEACHER_PREFIX,requestContext);
            return null;
        }

        //管理员
        if (ArrayAuthUtils.ArrayContains(ADMIN_WHITE,url)){
            //从header中取出ADMIN-TOKEN及ADMIN-ID
            String token = request.getHeader("ADMIN-TOKEN");
            String adminId = request.getHeader("ADMIN-ID");
            verifyTokenAndId(token,adminId,ADMIN_PREFIX,requestContext);
            return null;
        }

        setUnauthorizedResponse(requestContext);
        return null;
    }


    /**
    * @Description 检验token和用户id
    * @Param [headerToken, headerId, redisPrefix]
    * @Return void
    * @Author Czz
    * @Date 2020/4/2
    * @Time 12:01
    **/
    private void verifyTokenAndId(String headerToken, String headerId, String redisPrefix, RequestContext context){
        //header不存在token或id
        if (StringUtils.isEmpty(headerToken) || StringUtils.isEmpty(headerId)){
            setUnauthorizedResponse(context);
        }
        //存在token，与redis中token对比
        String redisToken = this.redisTemplate.opsForValue().get(redisPrefix + headerId);

        //redis中不存在此用户token或者token对比不一致
        if (StringUtils.isEmpty(redisToken) || ! headerToken.equals(redisToken)){
            setUnauthorizedResponse(context);
        }
    }

    /**
    * @Description 设置无权限返回
    * @Param [requestContext]
    * @Return void
    * @Author Czz
    * @Date 2020/4/2
    * @Time 11:59
    **/
    private void setUnauthorizedResponse(RequestContext requestContext) {
        // 过滤该请求，不对其进行路由
        requestContext.setSendZuulResponse(false);
        requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        requestContext.setResponseBody("{\"success\":\"false\",\"code\":\"21008\", \"message\":\"权限不足！\"}");
        requestContext.getResponse().setContentType("text/html;charset=utf-8");
    }
}
